//-----------------------------------------------------
// nebulaApplication.cpp
//-----------------------------------------------------

/**
 * comment here
 */

#include "nebulaApplication.h"
#include "nebulaGameState.h"

#include <assert.h>

#include "kernel/nkernelserver.h"
#include "kernel/nfileserver2.h"
#include "resource/nresourceserver.h"
#include "gfx2/ngfxserver2.h"
#include "input/ninputserver.h"

namespace application {

	// Declare packages
	nNebulaUsePackage(nnebula);
	nNebulaUsePackage(ndirect3d9);
	nNebulaUsePackage(ngui);
	nNebulaUsePackage(ndinput8);

	CNebulaApplication::CNebulaApplication() {}
	CNebulaApplication::~CNebulaApplication() {}

	bool CNebulaApplication::init()
	{
		if(!CApplication::init())
			return false;

		initNebula();

		this->addState("game", new CNebulaGameState(this));
		this->setState("game");

		return true;
	}

	void CNebulaApplication::end()
	{
		CApplication::end();
		endNebula();
	}

	bool CNebulaApplication::initNebula()
	{
		kernelServer = new nKernelServer;

		// All packages have to be declared and added before you use them
		kernelServer->AddPackage(nnebula);
		kernelServer->AddPackage(ndirect3d9);
		kernelServer->AddPackage(ngui);
		kernelServer->AddPackage(ndinput8);

		this->refResourceServer = (nResourceServer*) kernelServer->New("nresourceserver", "/sys/servers/resource");
		this->refGfxServer = (nGfxServer2*) kernelServer->New("nd3d9server", "/sys/servers/gfx");
		this->refSceneServer = (nSceneServer*) kernelServer->New("nmrtsceneserver", "/sys/servers/scene");
		this->refVarServer = (nVariableServer*) kernelServer->New("nvariableserver", "/sys/servers/variable");
		this->refShadowServer = (nShadowServer*) kernelServer->New("nshadowserver", "/sys/servers/shadow");
		this->refGuiServer = (nGuiServer*) kernelServer->New("nguiserver", "/sys/servers/gui");
		this->refConServer = (nConServer*) kernelServer->New("nconserver", "/sys/servers/console");

		// set shaders assign, needed for the gfx server,
		// this means that "shaders:" can be used to refer to the given directory.
		kernelServer->GetFileServer()->SetAssign("shaders", "home:data/shaders/fixed");

		nDisplayMode2 DisplayMode("Engine", nDisplayMode2::Windowed, 0, 0, 640, 480, false);
		refGfxServer->SetDisplayMode(DisplayMode);
		refGfxServer->SetCamera(gfxCamera);

		this->refSceneServer->SetRenderPathFilename("data/shaders/dx9hdr_renderpath.xml");

		// Open the scene server, and as a side effect the graphic server
		if (!this->refSceneServer->Open()) 
		{
			this->end();
			return false;
		}

		// Create the input server. It must be done after sceneServer->Open(), because it only
		// works if gfxServer->OpenDisplay() has been called

		this->refInputServer = (nInputServer*)this->kernelServer->New("ndi8server", "/sys/servers/input");

		// TODO: Map input

		this->refInputServer->BeginMap();
		//.map "keyb0:f11.down" "console"
		//this->refInputServer->Map("keyb0:f11.down", "console");
		this->refInputServer->Map("relmouse0:btn0.pressed", "look");
		this->refInputServer->Map("relmouse0:btn1.pressed", "zoom");
		this->refInputServer->Map("relmouse0:btn2.pressed", "pan");
		this->refInputServer->Map("keyb0:space.down", "reset");
		this->refInputServer->Map("relmouse0:-x", "left");
		this->refInputServer->Map("relmouse0:+x", "right");
		this->refInputServer->Map("relmouse0:-y", "up");
		this->refInputServer->Map("relmouse0:+y", "down");
		this->refInputServer->EndMap();

		//bool result;
		//result = refGfxServer->OpenDisplay();
		//assert(result && "Error creating nebula display");
		 
		// to avoid dereferencing the nRef all the time
		// get a pointer to the gfx server. 
		gfxServer = refGfxServer.get();

		return true;
	}

	void CNebulaApplication::endNebula()
	{
		refConServer->Release();
		refGuiServer->Release();
		refShadowServer->Release();
		refVarServer->Release();
		refSceneServer->Release();

		refGfxServer->CloseDisplay();

		refGfxServer->Release();
		refResourceServer->Release();

		delete kernelServer;
	}

	//void CNebulaApplication::run()
	//{
	//	// trigger the gfx server once every frame
	//	// Trigger() returns false if you close the window
	//	while (gfxServer->Trigger())
	//	{
	//		gfxServer->BeginScene();
	//		//gfxServer->Clear(nGfxServer2::AllBuffers, 0.0f, 0.8f, 0.6f, 0.4f, 0.0f, 0);
	//		gfxServer->Clear(nGfxServer2::AllBuffers, 0.0f, 0.0f, 0.0f, 0.4f, 0.0f, 0);


	//		gfxServer->EndScene();
	//		gfxServer->PresentScene();

	//		// allow Windows to multitask
	//		n_sleep(0.0);
	//	}
	//}

} // namespace application